package cn._2dland.gae.httpclient.method;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.zip.GZIPInputStream;

import cn._2dland.gae.httpclient.Cookie;
import cn._2dland.gae.httpclient.HttpClientParams;
import cn._2dland.gae.httpclient.NameValuePair;

public abstract class HttpMethod {
	protected HttpURLConnection conn;

	// 请求相关属性
	protected String url = null;
	protected Map<String, String> requestHeaders = null;
	protected Map<String, String> parameters = null;
	protected HttpClientParams params = new HttpClientParams();

	// 响应相关属性
	protected Map<String, String> responseHeaders = null;
	protected String serverCharset = "utf-8";
	protected List<Cookie> cookies = new ArrayList<Cookie>();

	public HttpMethod(){}
	public HttpMethod(String url){
		this.url = url;
	}

	/** 获取参数 */
	public HttpClientParams getParams() {
		return params;
	}

	/** 获取方法名称 */
	abstract public String getMethodName();

	/** URL地址 */
	public void setURL(String url) {
		this.url = url;
	}
	protected String getURL() {
		return this.url;
	}

	/** 获取要提交的数据 */
	protected byte[] getData() {
		return null;
	}

	/** 添加请求头 */
	public void addRequestHeader(NameValuePair header) {
		if(header == null) return;
		if(requestHeaders == null)
			requestHeaders = new HashMap<String, String>();
		requestHeaders.put(header.name, header.value);
	}
	public void addRequestHeader(String name, String value) {
		addRequestHeader(new NameValuePair(name ,value));
	}
	public void addRequestHeaders(NameValuePair[] headers) {
		for(int i=0; headers!=null && i<headers.length; i++)
			addRequestHeader(headers[i]);
	}

	/** 添加HTTP参数 */
	public void addParameter(NameValuePair param) {
		if(param == null)
			return;
		if(parameters == null)
			parameters = new HashMap<String, String>();
		parameters.put(param.name, param.value);
	}
	public void addParameter(String name, String value) {
		addParameter(new NameValuePair(name ,value));
	}
	public void addParameters(NameValuePair[] params) {
		for(int i=0; params!=null && i<params.length; i++)
			addParameter(params[i]);
	}

	/** 执行HTTP方法 */
	public int execute() {
		int respCode = 0;
		try {
			URL u = new URL(getURL());
			conn = (HttpURLConnection)u.openConnection();
			conn.setRequestMethod(getMethodName());
			conn.setDoInput(true);
			conn.setDoOutput(true);
			conn.setInstanceFollowRedirects(params.isFollowRedirect());
			conn.setUseCaches(params.isUseCaches());

			// 设置请求头
			conn.setRequestProperty("User-Agent", params.getUserAgent());
			if(requestHeaders != null) {
				Iterator<Entry<String, String>> hs = requestHeaders.entrySet().iterator();
				while(hs.hasNext()) {
					Entry<String, String> h = hs.next();
					conn.setRequestProperty(h.getKey(), h.getValue());
				}
			}
			// 发起连接
			conn.connect();

			// 判断是否有需要写入的数据
			byte[] data = getData();
			if(data != null) {
				OutputStream os = conn.getOutputStream();
				os.write(data);
				os.flush();
			}

			respCode = conn.getResponseCode();

			// 填充响应头
			responseHeaders = new HashMap<String, String>();
			Iterator<Entry<String, List<String>>> hs = conn.getHeaderFields().entrySet().iterator();
			while(hs.hasNext()) {
				Entry<String, List<String>> h = hs.next();
				if(h.getKey() == null)
					continue;
				// 保存cookie信息
				if("set-cookie".equalsIgnoreCase(h.getKey())) {
					saveCookie(h.getValue());
					continue;
				}
				responseHeaders.put(h.getKey(), h.getValue().get(0));
			}

			// 获取响应信息的编码
			String ctntType = conn.getContentType();
			if(ctntType != null && ctntType.indexOf("charset=") >= 0) {
				serverCharset = ctntType.substring(ctntType.indexOf("charset=") + 8).trim();
			}
			else {
				serverCharset = "utf-8";
			}
		}
		catch (Exception e) {
			e.printStackTrace();
		}
		return respCode;
	}

	/** 获取响应头 */
	public String getResponseHeader(String header) {
		return responseHeaders.get(header);
	}
	/** 获取Cookie */
	public List<Cookie> getCookies() {
		return cookies;
	}
	/** 获取响应流 */
	public InputStream getResponseStream() {
		InputStream stream = null;
		try{ stream = conn.getInputStream(); }
		catch (Exception e) { }
		return stream;
	}
	/** 获取响应文本 */
	public String getResponseString() {
		String body = null;
		try {
			// 获取结果流
			InputStream is = conn.getInputStream();
			// 判断是否需要解压
			String enc = responseHeaders.get("Content-Encoding");
			if(enc != null && enc.indexOf("gzip")>=0)
				is = new GZIPInputStream(is);

			// 读取结果流，并构建字符串
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			for(int b; (b=is.read()) >= 0; )
				baos.write(b);
			baos.flush();
			body = new String(baos.toByteArray(), serverCharset);

			// 释放资源
			baos.close();
			is.close();
		}
		catch (Exception e) {
			e.printStackTrace();
		}
		return body;
	}

	/** 释放连接 */
	public void releaseConnection() {
		conn.disconnect();
	}

	/** 保存Cookie */
	private void saveCookie(List<String> rawCookie) {
		cookies.clear();
		for(int i=0; rawCookie!=null && i<rawCookie.size(); i++) {
			String s = rawCookie.get(i);
			Cookie c = Cookie.parse(s);
			if(c != null) cookies.add(c);
		}
	}
}
